import {
	_decorator,
	Component,
	Slider,
	Camera,
	geometry,
	input,
	Input,
	EventTouch,
	PhysicsSystem,
	Vec3,
	Prefab,
	Node,
	Color,
	instantiate,
} from 'cc';
import { shuffle } from '../goldMiner/utils';
import { Rotation } from './utils/rotation';
import { levelData, Surface } from './levelData';
import Global from '../common/Global';
import { FoldCubeSurface } from './FoldCubeSurface';
import { sleep } from '../matchstick/utils';
import { SliderActived } from './SliderActived';
import { MultipleAudioControler } from '../logicalReasoning/MultipleAudioControler';
const { ccclass, property } = _decorator;

const colorList = ['FF0C0C', 'FF8603', '#5EFF03', '03EBFF', '054BFD', 'CB05FD'];
@ccclass('FoldCube')
export class FoldCube extends Component {
	// 3D相机
	@property(Camera)
	readonly camera!: Camera;
	originPosition: Vec3 = new Vec3();

	@property(Prefab)
	surfacePrefab!: Prefab;

	@property(Node)
	cube: Node = null;

	@property(Node)
	popup: Node = null;

	@property(Node)
	progressBar: Node = null;

	@property(Node)
	slider: Node = null;

	private level: number = 0;
	private _ray: geometry.Ray = new geometry.Ray();
	private axisY: Vec3 = new Vec3(0, 1, 0);
	private angle: number = 0;
	//color 索引
	private index: number = 0;
	private colors: string[];
	private color: Color = new Color();
	private totalFace: number = 5;

	player: MultipleAudioControler;

	start() {
		if (!Global.gameOrderBy) {
			Global.gameOrderBy = 9;
		}
		this.camera.node.getWorldPosition(this.originPosition);
		this.player = this.node.getComponent(MultipleAudioControler);
		this.initData();
	}

	initData() {
		this.index = 0;
		this.totalFace = 5;
		this.angle = 0;
		this.slider.getComponent(Slider).progress = 0;
		this.progressBar.getComponent(SliderActived).resetWidth();
		this.colors = shuffle(colorList);
		this.level = Global.gameOrderBy - 1;
		if (this.level >= 8) {
			this.cube.setScale(0.998, 0.498, 0.998);
		} else {
			this.cube.setScale(0.998, 0.998, 0.998);
		}
		let { surface } = levelData[this.level];
		this.camera.node.setWorldPosition(this.originPosition);
		this.createSurface(this.node, surface);
		this.camera.node.lookAt(this.node.position);
	}

	createSurface(parent: Node, surface: Surface) {
		let surfaceNode = instantiate(this.surfacePrefab);
		let {
			position: p,
			rotation: r,
			scale: s = new Vec3(1, 1, 1),
			active,
			children,
		} = surface;
		surfaceNode.setParent(parent);
		surfaceNode.setPosition(p.x, p.y, p.z);
		surfaceNode.setRotationFromEuler(r.x, r.y, r.z);
		surfaceNode.setScale(s.x, s.y, s.z);
		Color.fromHEX(this.color, this.colors[this.index]);
		let foldSurface = surfaceNode.getComponent(FoldCubeSurface);
		foldSurface.initColor(this.color);
		this.index++;
		foldSurface.active = active;
		if (children.length) {
			children.forEach((child) => {
				let { surface } = child;
				this.createSurface(surfaceNode, surface);
			});
		}
	}

	rotate(slider: Slider) {
		let { progress = 0 } = slider;
		let angle = progress * 360 - this.angle;
		this.angle += angle;
		Rotation.rotationAroundNode(this.camera.node, this.node, this.axisY, angle);
		this.camera.node.lookAt(this.node.position);
	}
	foldOneSurface() {
		--this.totalFace;
		if (this.totalFace <= 0) {
			this.showEndAnimate();
			this.levelPassed();
		}
	}
	resetNodes() {
		let surface = this.node.getChildByName('surface');
		surface.destroy();
		this.initData();
	}
	showEndAnimate() {}
	nextLevel() {
		this.popup.active = false;
		Global.gameOrderBy++;
		this.resetNodes();
	}
	async levelPassed() {
		this.player.play('通关成功');
		await sleep(1);
		this.popup.active = true;
	}
	onEnable() {
		input.on(Input.EventType.TOUCH_START, this.touchStart, this);
	}

	onDisable() {
		input.off(Input.EventType.TOUCH_START, this.touchStart, this);
	}

	touchStart(event: EventTouch) {
		const touch = event.touch!;
		this.camera.screenPointToRay(
			touch.getLocationX(),
			touch.getLocationY(),
			this._ray
		);

		if (PhysicsSystem.instance.raycastClosest(this._ray)) {
			const result = PhysicsSystem.instance.raycastClosestResult;
			if (!result) return;
			let node = result.collider.node;
			let surface = node.getComponent(FoldCubeSurface);
			surface.rotateFace();
		}
	}

	update(deltaTime: number) {}
}
